home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * xwind.c
- *
- * This file contains the XWindows code for the display-as-you-trace feature.
- *
- * from Persistence of Vision Raytracer
- * Copyright 1993 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * NOTICE: This source code file is provided so that users may experiment
- * with enhancements to POV-Ray and to port the software to platforms other
- * than those supported by the POV-Ray Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file. If
- * POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by leaving a message in CompuServe's Graphics Developer's
- * Forum. The latest version of POV-Ray may be found there as well.
- *
- * This program is based on the popular DKB raytracer version 2.12.
- * DKBTrace was originally written by David K. Buck.
- * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- *
- *****************************************************************************/
-
- /******************************************************************************/
- /* */
- /* X Windows code for POV-Ray. */
- /* Written by Christopher J. Cason. */
- /* CIS 100032,1644 */
- /* Internet 100032.1644@compuserve.com */
- /* */
- /******************************************************************************/
-
- /******************************************************************************/
- /* */
- /* Original IBM VGA "colour" output routines for MS/DOS by Aaron A. Collins. */
- /* */
- /* Converted for X Windows and arbitrary #of colours by Christopher J. Cason. */
- /* */
- /* This will deliver approximate colorings using HSV values for the selection.*/
- /* The palette map is divided into 4 parts - upper and lower half generated */
- /* with full and half "value" (intensity), respectively. These halves are */
- /* further halved by full and half saturation values of each range (pastels). */
- /* There are three constant colors, black, white, and grey. They are used */
- /* when the saturation is low enough that the hue becomes undefined, and which*/
- /* one is selected is based on a simple range map of "value". Usage of the */
- /* palette is accomplished by converting the requested color RGB into an HSV */
- /* value. If the saturation is too low (< .25) then black, white or grey is */
- /* selected. If there is enough saturation to consider looking at the hue, */
- /* then the hue range of 1-63 is scaled into one of the 4 palette quadrants */
- /* based on its "value" and "saturation" characteristics. */
- /* */
- /******************************************************************************/
-
- /******************************************************************************/
- /* */
- /* define X_GETS_ARGS if you want to use X options such as '-display xxx:n.n' */
- /* */
- /******************************************************************************/
-
- #define DBL double
- #define NAME "POV-Ray"
-
- #include <stdio.h>
- #include <math.h>
- #include <x11/xlib.h>
- #include <x11/xutil.h>
- #include <x11/stringdefs.h>
- #include <x11/intrinsic.h>
- #include <x11/shell.h>
- #include "config.h"
-
- #define MIN_COLOURS 128
- #define MAX_COLOURS 256
-
- #define min(x,y) ((x) < (y) ? (x) : (y))
- #define max(x,y) ((x) > (y) ? (x) : (y))
-
- char filename [192] ; /* don't really need it */
- unsigned gWidth ; /* +wxxx */
- unsigned gHeight ; /* +hyyy */
- unsigned gScreenNumber ; /* screen number */
- unsigned nColours ; /* colours available */
- unsigned quarterPalette ; /* 1/4 of nColours */
- unsigned CooperationLevel = 5 ; /* for message loop */
- unsigned screenWidth ; /* of root screen */
- unsigned screenHeight ; /* ditto */
- unsigned long gColours [MAX_COLOURS] ; /* colour lookup */
- GC gGc ; /* graphics context */
- Screen *gScreen ; /* the X screen */
- XImage *gXimage = NULL ; /* to buffer the trace */
- Widget gParent ; /* parent widget */
- Widget gPopupwindow ; /* trace displayed here */
- Window gWindow ; /* child of gPopupWin.. */
- Display *gDisplay ; /* X display connection */
- Colormap gColourmap ; /* the colourmap */
- XtAppContext gAppcontext ; /* application context */
-
- /* in POVRAY.C */
- unsigned alt_main (unsigned argc, char *argv []) ;
-
- /******************************************************************************/
- /* */
- /* set a pixel in an XImage */
- /* */
- /******************************************************************************/
-
- void SetPixel (Display *display, XImage *ximage, Window window, GC gc, unsigned x, unsigned y, unsigned index)
- {
- static unsigned lastY = 0 ;
-
- if (lastY > y) lastY = y ;
- if (y != lastY)
- {
- /* for efficiency, only display the pixels after a full line is buffered */
- XPutImage (display, window, gc, ximage, 0, lastY, 0, lastY, gWidth, gHeight) ;
- lastY = y ;
- }
- XPutPixel (ximage, x, y, gColours [index]) ;
- }
-
- /******************************************************************************/
- /* */
- /* create an XImage */
- /* */
- /******************************************************************************/
-
- XImage *CreateXImage (Display *display, Visual *visual,
- unsigned depth, unsigned width, unsigned height)
- {
- unsigned format ;
- unsigned number_of_bytes ;
- XImage *ximage ;
-
- format = depth == 1 ? XYBitmap : ZPixmap ;
-
- ximage = XCreateImage (display, visual, depth, format,
- 0, NULL, width, height, XBitmapPad (display), 0) ;
-
- if (ximage == NULL) return (NULL) ;
-
- number_of_bytes = ximage->bytes_per_line * ximage->height ;
- if ((ximage->data = malloc (number_of_bytes)) == NULL) return (NULL) ;
- return (ximage) ;
- }
-
- /******************************************************************************/
- /* */
- /* create an XImage to be compatible with the supplied widget */
- /* */
- /******************************************************************************/
-
- XImage *CreateXImageFromWidget (Widget widget, unsigned width, unsigned height)
- {
- unsigned depth ;
- XImage *ximage ;
- Visual *visual ;
- Display *display ;
-
- XtVaGetValues (widget, XtNdepth, &depth, XtNvisual, &visual, NULL) ;
- display = XtDisplay (widget) ;
- ximage = CreateXImage (display, visual, depth, width, height) ;
- return (ximage) ;
- }
-
- /******************************************************************************/
- /* */
- /* make an XImage given a widget, width and height */
- /* */
- /******************************************************************************/
-
- XImage *MakeImage (Widget widget, unsigned width, unsigned height)
- {
- unsigned x ;
- unsigned y ;
- XImage *ximage ;
-
- if ((ximage = CreateXImageFromWidget (widget, width, height)) != NULL)
- {
- for (x = 0 ; x < width ; x++)
- for (y = 0 ; y < height ; y++)
- XPutPixel (ximage, x, y, gColours [0]) ;
- }
-
- return (ximage) ;
- }
-
- /******************************************************************************/
- /* */
- /* redraw the traced data using the XImage */
- /* */
- /******************************************************************************/
-
- void processExpose (XExposeEvent *expose)
- {
- if (gXimage == NULL || (void *) gWindow == NULL) return ;
- XPutImage (gDisplay, gWindow, gGc, gXimage,
- expose->x, expose->y,
- expose->x, expose->y,
- expose->width, expose->height) ;
- }
-
- /******************************************************************************/
- /* */
- /* this is called by the COOPERATE macro from within POVRAY */
- /* */
- /******************************************************************************/
-
- void XTraceEventHandler (void)
- {
- XEvent event ;
- static unsigned cooperationCounter = 10 ;
-
- if (CooperationLevel < 10 && --cooperationCounter) return ;
- cooperationCounter = 11 - CooperationLevel ;
-
- if (CooperationLevel > 5)
- {
- /* loop until all messages retrieved */
- while (XtAppPending (gAppcontext))
- {
- XtAppNextEvent (gAppcontext, &event) ;
- if (event.type == Expose && event.xexpose.window == gWindow)
- {
- if (event.xexpose.count == 0) processExpose (&event.xexpose) ;
- return ;
- }
- XtDispatchEvent (&event) ;
- }
- }
- else
- {
- /* only process 1 event */
- if (XtAppPending (gAppcontext))
- {
- XtAppNextEvent (gAppcontext, &event) ;
- if (event.type == Expose && event.xexpose.window == gWindow)
- {
- if (event.xexpose.count == 0) processExpose (&event.xexpose) ;
- return ;
- }
- XtDispatchEvent (&event) ;
- }
- }
- }
-
- /******************************************************************************/
- /* */
- /* called if the user closes the popup window during a trace */
- /* */
- /******************************************************************************/
-
- void destroyProc (Widget widget)
- {
- XDestroyImage (gXimage) ;
- XFreeGC (gDisplay, gGc) ;
- gPopupwindow = NULL ;
- }
-
- /******************************************************************************/
- /* */
- /* create a popup window, centered on the screen */
- /* */
- /******************************************************************************/
-
- Widget CreatePopupWindow (Widget parent, char *name, unsigned width, unsigned height, void (*destroyProc) (Widget))
- {
- int n ;
- unsigned x = 0 ;
- unsigned y = 0 ;
- Arg args [8] ;
- Widget window ;
-
- n = 0 ;
- if (width < screenWidth)
- x = screenWidth / 2 - width / 2 ;
- if (height < screenHeight)
- y = screenHeight / 2 - height / 2 ;
- XtSetArg (args [n], XtNwidth, width) ; n++ ;
- XtSetArg (args [n], XtNheight, height) ; n++ ;
- XtSetArg (args [n], XtNx, x) ; n++ ;
- XtSetArg (args [n], XtNy, y) ; n++ ;
- window = XtCreatePopupShell (name, topLevelShellWidgetClass, parent, args, n) ;
- XtAddCallback (window, XtNdestroyCallback, destroyProc, window) ;
- return (window) ;
- }
-
- /******************************************************************************/
- /* */
- /* allocate a colour based on the RGB values and place it at index */
- /* */
- /******************************************************************************/
-
- void set_palette (unsigned index, unsigned red, unsigned green, unsigned blue)
- {
- XColor colour ;
-
- colour.pixel = gColours [index] ;
- colour.flags = DoRed | DoGreen | DoBlue ;
- colour.red = (65535 * red) / 256 ;
- colour.blue = (65535 * blue) / 256 ;
- colour.green = (65535 * green) / 256 ;
- XStoreColor (gDisplay, gColourmap, &colour) ;
- }
-
- /******************************************************************************/
- /* */
- /* Conversion from Hue, Saturation, Value to Red, Green, and Blue and back */
- /* From "Computer Graphics", Donald Hearn & M. Pauline Baker, p. 304 */
- /* Extracted from the POV machine specific file IBM.C and modified for X */
- /* */
- /* See the start of this file for information as to how this code works */
- /* */
- /******************************************************************************/
-
- void hsv_to_rgb (DBL hue, DBL s, DBL v, unsigned *r, unsigned *g, unsigned *b)
- {
- DBL i ;
- DBL f ;
- DBL p1 ;
- DBL p2 ;
- DBL p3 ;
- DBL xh ;
- DBL nr ;
- DBL ng ;
- DBL nb ;
-
- if (hue == 360.0) hue = 0.0 ;
-
- xh = hue / 60.0 ; /* convert hue to be in 0..6 */
- i = floor (xh) ; /* i = greatest integer <= h */
- f = xh - i ; /* f = fractional part of h */
- p1 = v * (1 - s) ;
- p2 = v * (1 - (s * f)) ;
- p3 = v * (1 - (s * (1 - f))) ;
-
- switch ((int) i)
- {
- case 0 :
- nr = v ;
- ng = p3 ;
- nb = p1 ;
- break ;
-
- case 1 :
- nr = p2 ;
- ng = v ;
- nb = p1 ;
- break ;
-
- case 2 :
- nr = p1 ;
- ng = v ;
- nb = p3 ;
- break ;
-
- case 3 :
- nr = p1 ;
- ng = p2 ;
- nb = v ;
- break ;
-
- case 4 :
- nr = p3 ;
- ng = p1 ;
- nb = v ;
- break ;
-
- case 5 :
- nr = v ;
- ng = p1 ;
- nb = p2 ;
- break ;
-
- default :
- nr = ng = nb = 0 ;
- }
- *r = (unsigned) (nr * 255.0) ;
- *g = (unsigned) (ng * 255.0) ;
- *b = (unsigned) (nb * 255.0) ;
- }
-
- void rgb_to_hsv (unsigned r, unsigned g, unsigned b, DBL *h, DBL *s, DBL *v)
- {
- DBL m ;
- DBL r1 ;
- DBL g1 ;
- DBL b1 ;
- DBL nr ;
- DBL ng ;
- DBL nb ;
- DBL nh = 0.0 ;
- DBL ns = 0.0 ;
- DBL nv ;
-
- nr = (DBL) r / 255.0 ;
- ng = (DBL) g / 255.0 ;
- nb = (DBL) b / 255.0 ;
-
- nv = max (nr, max (ng, nb)) ;
- m = min (nr, min (ng, nb)) ;
-
- if (nv != 0.0) ns = (nv - m) / nv ;
-
- if (ns == 0.0)
- {
- /* hue undefined if no saturation */
- *h = 0.0 ;
- *s = 0.0 ;
- *v = nv ;
- return ;
- }
-
- r1 = (nv - nr) / (nv - m) ; /* distance of color from red */
- g1 = (nv - ng) / (nv - m) ; /* distance of color from green */
- b1 = (nv - nb) / (nv - m) ; /* distance of color from blue */
-
- if (nv == nr)
- {
- if (m == ng)
- nh = 5.0 + b1 ;
- else
- nh = 1.0 - g1 ;
- }
-
- if (nv == ng)
- {
- if (m == nb)
- nh = 1.0 + r1 ;
- else
- nh = 3.0 - b1 ;
- }
-
- if (nv == nb)
- {
- if (m == nr)
- nh = 3.0 + g1 ;
- else
- nh = 5.0 - r1 ;
- }
-
- *h = nh * 60.0 ; /* return h converted to degrees */
- *s = ns ;
- *v = nv ;
- }
-
- /******************************************************************************/
- /* */
- /* set up the X palette */
- /* try to allocate at least as many colours as MIN_COLOURS */
- /* exit with an error if we cannot get at least this many */
- /* divide the available colour up into four quadrants, and divide each */
- /* quadrant up into specific hues from 0 to 359 degrees */
- /* */
- /******************************************************************************/
-
- void palette_init (void)
- {
- unsigned m ;
- unsigned r ;
- unsigned g ;
- unsigned b ;
- DBL hue ;
- DBL sat ;
- DBL val ;
-
- for (nColours = MAX_COLOURS ; nColours >= MIN_COLOURS ; nColours--)
- if (XAllocColorCells (gDisplay, gColourmap, False, NULL, 0, gColours, nColours))
- break ;
- if (nColours < MIN_COLOURS)
- {
- printf ("failed to allocate colour cells needed for display\r\n") ;
- exit (1) ;
- }
-
- quarterPalette = nColours / 4 ;
-
- /* for the first quarter of the palette ... */
- for (m = 1 ; m < quarterPalette ; m++)
- {
- /* normalise to 360 */
- hue = 360.0 * ((DBL) (m)) / (DBL) quarterPalette ;
- hsv_to_rgb (hue, 0.5, 0.5, &r, &g, &b) ;
- set_palette (m, r, g, b) ;
-
- hue = 360.0 * ((DBL) (m)) / (DBL) quarterPalette ;
- hsv_to_rgb (hue, 1.0, 0.5, &r, &g, &b) ;
- set_palette (m + quarterPalette, r, g, b) ;
-
- hue = 360.0 * ((DBL) (m)) / (DBL) quarterPalette ;
- hsv_to_rgb (hue, 0.5, 1.0, &r, &g, &b) ;
- set_palette (m + quarterPalette * 2, r, g, b) ;
-
- hue = 360.0 * ((DBL) (m)) / (DBL) quarterPalette ;
- hsv_to_rgb (hue, 1.0, 1.0, &r, &g, &b) ;
- set_palette (m + quarterPalette * 3, r, g, b) ;
- }
-
- set_palette (0, 0, 0, 0) ; /* black */
- set_palette (quarterPalette, 255, 255, 255) ; /* white */
- set_palette (quarterPalette * 2, 128, 128, 128) ; /* dark grey */
- set_palette (quarterPalette * 3, 192, 192, 192) ; /* light grey */
- }
-
- /******************************************************************************/
- /* */
- /* display code called directly by POV-Ray via [machine-name].C */
- /* */
- /******************************************************************************/
-
- void x_display_finished ()
- {
- }
-
- void x_display_init (unsigned width, unsigned height)
- {
- unsigned n ;
- unsigned y = 0 ;
- unsigned x = 0 ;
- unsigned long white ;
- unsigned long black ;
- Arg args [20] ;
-
- gDisplay = XtDisplay (gParent) ;
- gScreen = XtScreen (gParent) ;
- gScreenNumber = XScreenNumberOfScreen (gScreen) ;
- gColourmap = DefaultColormapOfScreen (gScreen) ;
- screenWidth = DisplayWidth (gDisplay, gScreenNumber) ;
- screenHeight = DisplayHeight (gDisplay, gScreenNumber) ;
-
- white = WhitePixel (gDisplay, gScreenNumber) ;
- black = BlackPixel (gDisplay, gScreenNumber) ;
-
- n = 0 ;
- x = screenWidth / 2 - gWidth / 2 ;
- y = screenHeight / 2 - gHeight / 2 ;
- XtSetArg (args [n], XtNx, x) ; n++ ;
- XtSetArg (args [n], XtNy, y) ; n++ ;
- XtSetValues (gParent, args, n) ;
-
- gWidth = width ;
- gHeight = height ;
- gPopupwindow = CreatePopupWindow (gParent, NAME, width, height, destroyProc) ;
-
- XtRealizeWidget (gPopupwindow) ;
- XtMapWidget (gPopupwindow) ;
-
- gWindow = XCreateSimpleWindow (gDisplay, XtWindow (gPopupwindow), 0, 0, width, height, 0, white, black) ;
- XSetWindowBackground (gDisplay, gWindow, black) ;
- XMapWindow (gDisplay, gWindow) ;
- XtPopup (gPopupwindow, XtGrabNonexclusive) ;
-
- palette_init () ;
-
- gGc = XCreateGC (gDisplay, gWindow, 0L, NULL) ;
- gXimage = MakeImage (gPopupwindow, width, height) ;
-
- /* draw a rectangle into the XImage to show trace progress */
-
- for (x = 0 ; x < width ; x++)
- {
- XPutPixel (gXimage, x, 0, white) ;
- XPutPixel (gXimage, x, height - 1, white) ;
- }
-
- for (y = 0 ; y < height ; y++)
- {
- XPutPixel (gXimage, 0, y, white) ;
- XPutPixel (gXimage, width - 1, y, white) ;
- }
-
- XSelectInput (gDisplay, gWindow, ExposureMask) ;
- }
-
- void x_display_close ()
- {
- if (gPopupwindow)
- XtDestroyWidget (gPopupwindow) ;
- }
-
- void x_display_plot (unsigned x, unsigned y, char Red, char Green, char Blue)
- {
- unsigned colour ;
- DBL h ;
- DBL s ;
- DBL v ;
-
- if (gPopupwindow == NULL) return ;
-
- rgb_to_hsv ((unsigned) Red, (unsigned) Green, (unsigned) Blue, &h, &s, &v) ;
-
- if (s < 0.20) /* black or white if no saturation of colour ... */
- {
- if (v < 0.25)
- colour = 0 ; /* black */
- else if (v > 0.8)
- colour = quarterPalette ; /* white */
- else if (v > 0.5)
- colour = quarterPalette * 3 ; /* light grey */
- else
- colour = quarterPalette * 2 ; /* dark grey */
- }
- else
- {
- colour = (unsigned) ((DBL) quarterPalette * h / 360.0) ;
-
- if (colour == 0)
- colour = 1 ; /* avoid black, white or grey */
-
- if (colour > quarterPalette)
- colour = quarterPalette ; /* avoid same */
-
- if (v > 0.50)
- colour += quarterPalette * 2 ; /* colours 128-255 for high intensity */
-
- if (s > 0.50) /* more than half saturated ? */
- colour += quarterPalette ; /* colour range 64-128 or 192-255 */
- }
-
- /* only displays after a full line is received (the Y co-ordinate changes) */
- SetPixel (gDisplay, gXimage, gWindow, gGc, x, y, colour) ;
- }
-
- /******************************************************************************/
- /* */
- /* our main routine. when XWIND is linked in this is main () for POV-Ray */
- /* */
- /******************************************************************************/
-
- int main (unsigned argc, char *argv [])
- {
- unsigned n ;
- unsigned count = 0 ;
- Arg args [20] ;
-
- strncpy (filename, argv [0], sizeof (filename)) ;
-
- n = 0 ;
- XtSetArg (args [n], XtNmappedWhenManaged, False) ; n++ ;
- XtSetArg (args [n], XtNallowShellResize, False) ; n++ ;
- XtSetArg (args [n], XtNwidth, 10) ; n++ ;
- XtSetArg (args [n], XtNheight, 10) ; n++ ;
-
- /* define X_GETS_ARGS if you want to use X options such as '-display xxx:n.n' */
-
- #ifdef X_GETS_ARGS
- gParent = XtAppInitialize (&gAppcontext, NAME, NULL, 0, &argc, argv, NULL, args, n) ;
- #else
- gParent = XtAppInitialize (&gAppcontext, NAME, NULL, 0, &count, NULL, NULL, args, n) ;
- #endif
-
- /* call POV-Ray ! */
- alt_main (argc, argv) ;
- return (0) ;
- }